#!/usr/bin/env ruby
require 'drb/acl'
require File.dirname(__FILE__) + "/../../config/boot.rb"
require RAILS_ROOT + '/vendor/plugins/backgroundrb/backgroundrb.rb'
require 'rubygems'
require 'active_record'
require 'yaml'
require 'optparse'
require 'erb'
# default options
OPTIONS = {
  :configfile => "backgroundrb",
  :detach => false
}

class Auto
  def self.start
    puts "Autostart..."
    CONFIG['autostart'].each do |key, entry|
      puts " #{entry['class']}"
      BackgrounDRb::MiddleMan.instance.new_worker(:class => entry['class'],
                         :args => entry['args'],
                         :job_key => key)
    end
    puts "done"
  end
end

ARGV.options do |o|
  script_name = File.basename($0)
  
  o.set_summary_indent('  ')
  o.banner =    "Usage: #{script_name} [options]"
  o.define_head "Start a BackgrounDRb server"
  o.separator   ""
  
  o.on("-c", "--config-file [filename]", String,
       "An optional alternate name for the BackgrounDRb config file",
       "Default: #{OPTIONS[:configfile]}")   { |OPTIONS[:configfile]| }
  o.on("-d", "--detach",
       "Daemonize (run in the background)") { |OPTIONS[:detach]| }
  
  o.separator ""

  o.on_tail("-h", "--help", "Show this help message.") { puts o; exit }
  
  o.parse!
end

defaults = {'host' => 'localhost', 
            'port' => '22222',
            'acl' => { 'order' => 'deny,allow', 'deny' => 'all', 'allow' => 'localhost 127.0.0.1' },
            'environment' => 'development',
            'timer_sleep' => 60,
            'database_yml' => 'config/database.yml',
            'load_rails'  => true,
            'autostart' => {}
            }
            
           
begin
  CONFIG = defaults.merge(YAML.load(ERB.new(IO.read("#{RAILS_ROOT}/config/#{OPTIONS[:configfile]}.yml")).result)) 
rescue
  CONFIG = defaults
end            
if CONFIG['load_rails']
  ActiveRecord::Base.allow_concurrency = true
  require File.dirname(__FILE__) + "/../../config/environment.rb"
  ActiveRecord::Base.establish_connection(YAML.load(ERB.new(IO.read("#{RAILS_ROOT}/#{CONFIG['database_yml']}")).result)[CONFIG['environment']])
end
# Require all worker classes in lib/workers/
Dir["#{RAILS_ROOT}/lib/workers/*.rb"].each{ |worker| require worker }

# DRb has an access control feature. Here we are installing the acl specified
# in the config file.
acl_order = ACL.const_get(CONFIG['acl']['order'].sub(',','_').sub(/\s/, '').upcase)
acl_list = %w{allow deny}.inject([]) do |list, permission|
  CONFIG['acl'][permission].split(' ').inject(list) { |l,v| l << permission << v; l } unless CONFIG['acl'][permission].nil?
  list
end
acl = ACL.new(acl_list, acl_order)
DRb.install_acl(acl)

# if the -d flag is specified, fork twice into a daemon and detach from the terminal.
if OPTIONS[:detach]
  fork{
    stdin = open '/dev/null', 'r'
    stdout = open '/dev/null', 'w'
    stderr = open '/dev/null', 'w'
    STDIN.reopen stdin
    STDOUT.reopen stdout
    STDERR.reopen stderr
    $0 = "backgroundrb"
    fork{
      middleman = BackgrounDRb::MiddleMan.instance
      middleman.set_sleep(CONFIG['timer_sleep'] || 60)
      middleman.start_timer
      DRb.start_service("druby://#{CONFIG['host']}:#{CONFIG['port']}", middleman)
      File.open("#{RAILS_ROOT}/log/backgroundrb.pid", 'w+'){|f| f.write(Process.pid)}
      Auto.start
      DRb.thread.join
    } and exit!
  }
else
  middleman = BackgrounDRb::MiddleMan.instance
  middleman.set_sleep(CONFIG['timer_sleep'] || 60)
  middleman.start_timer
  DRb.start_service("druby://#{CONFIG['host']}:#{CONFIG['port']}", middleman)
  puts "DRb URI: #{DRb.uri}"
  puts "Pid: #{Process.pid}"
  File.open("#{RAILS_ROOT}/log/backgroundrb.pid", 'w+'){|f| f.write(Process.pid)}
  Auto.start
  DRb.thread.join
end